/*
 * Copyright © 2017 eqxiu.com 北京中网易企秀科技有限公司  All rights reserved.
 */
package cn.hermit.data.xml.model;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import cn.hermit.core.Entry;
import cn.hermit.util.StringUtils;

/**
 * Abstract class for XML node which has QName.
 * 
 * @author Jack Gao (Chinese name : GAO JIANGUO, Email : linux.gjg@gmail.com)
 * @date 19 Jun, 2014
 */
public abstract class XmlNameNode extends XmlNode {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2807652082638430398L;

	QName name;

	XmlNameNode() {
	}

	/**
	 * Get QName of XML node.
	 * 
	 * @return 
	 * 		The QName
	 */
	public QName getName() {
		return name;
	}

	/**
	 * Get prefix of XML tag.
	 * 
	 * @param tag
	 * 		The XML tag
	 * @return
	 * 		The prefix
	 */
	public static String getPrefix(String tag) {
		if (StringUtils.isEmpty(tag))
			return null;
		if(XMLConstants.XMLNS_ATTRIBUTE.equals(tag)){
			return XMLConstants.DEFAULT_NS_PREFIX;
		}
		int index = tag.indexOf(':');
		if (index == -1) {
			return XMLConstants.DEFAULT_NS_PREFIX;
		}else{
			String prefix = tag.substring(0, index);
			if(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)){
				return tag.substring(index+1);
			}else{
				return prefix;
			}
		}
	}

	/**
	 * Get local part of XML tag.
	 * 
	 * @param tag
	 * 		The XML tag
	 * @return
	 * 		The local part
	 */
	public static String getLocalPart(String tag) {
		if (StringUtils.isEmpty(tag))
			return null;
		int index = tag.indexOf(':');
		if (index == -1) {
			return tag;
		}
		return tag.substring(index + 1);
	}

	/**
	 * Get prefix and local part of XML tag
	 * @param tag
	 * 		The XML tag
	 * @return
	 * 		An entry which key is prefix and value is local part
	 */
	public static Entry<String, String> getNameInfo(String tag) {
		if (StringUtils.isEmpty(tag))
			return null;
		String prefix = null;
		String localPart = null;
		int index = tag.indexOf(':');
		if (index == -1) {
			prefix = XMLConstants.DEFAULT_NS_PREFIX;
			localPart = tag;
			return new Entry<String, String>(prefix, localPart);
		} else {
			prefix = tag.substring(0, index);
			localPart = tag.substring(index + 1);
			if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
				return new Entry<String, String>(localPart, prefix);
			} else {
				return new Entry<String, String>(prefix, localPart);
			}
		}
	}

	/**
	 * Get prefix of NameSpace attribute key.
	 * 
	 * @param key
	 * 		The NameSpace attribute key
	 * @return
	 * 		The prefix
	 */
	public static String getNamespacePrefix(String key) {
		if (StringUtils.isEmpty(key)) {
			return null;
		}
		int index = key.indexOf(':');
		if (index == -1) {
			return XMLConstants.DEFAULT_NS_PREFIX;
		}
		return key.substring(index + 1);
	}

	/**
	 * Check if a QName is NameSpace's name.
	 * 
	 * @param name
	 * 		A QName
	 * @return
	 */
	public static boolean isNamespaceName(QName name) {
		if (name == null)
			return false;
		return name.getLocalPart().equals(XMLConstants.XMLNS_ATTRIBUTE);
	}

	/**
	 * Check if a key is NameSpace's key.
	 * 
	 * @param key
	 * 		The NameSpace's key
	 * @return
	 */
	public static boolean isNamespaceName(String key) {
		if (key == null)
			return false;
		return key.startsWith(XMLConstants.XMLNS_ATTRIBUTE);
	}

	/**
	 * Get name string from a QName.
	 * 
	 * @param name
	 * 		A QName
	 * @return
	 * 		Name string
	 */
	public static String getName(QName name) {
		if (name == null)
			return null;
		if (StringUtils.isEmpty(name.getPrefix())) {
			return name.getLocalPart();
		} else {
			if (XMLConstants.XMLNS_ATTRIBUTE.equals(name.getLocalPart())) {
				return name.getLocalPart() + ':' + name.getPrefix();
			} else {
				return name.getPrefix() + ':' + name.getLocalPart();
			}
		}
	}

	/**
	 * Get QName of the NamedNode.
	 * 
	 * @param key
	 * 		Key of the NamedNode
	 * @return
	 * 		QName of the NamedNode
	 */
	public static QName getName(String key) {
		return getName(key, XMLConstants.NULL_NS_URI);
	}

	/**
	 * Get QName with key and NameSpace URL.
	 * 
	 * @param key
	 * 		A key
	 * @param namespaceURL
	 * 		A NameSpace URL
	 * @return
	 * 		A QName
	 */
	public static QName getName(String key, String namespaceURL) {
		if (namespaceURL == null)
			namespaceURL = XMLConstants.NULL_NS_URI;
		if (key == null)
			return null;
		int index = key.indexOf(':');
		String prefix = XMLConstants.DEFAULT_NS_PREFIX;
		String localPart = null;
		if (index == -1) {
			localPart = key;
		} else {
			prefix = key.substring(0, index);
			if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
				localPart = prefix;
				prefix = key.substring(index + 1);
			} else {
				localPart = key.substring(index + 1);
			}
		}
		return new QName(namespaceURL, localPart, prefix);
	}
	
	@Override
	public boolean isDocument() {
		return false;
	}

	@Override
	public boolean isElement() {
		return false;
	}

	@Override
	public boolean isAttribute() {
		return false;
	}

	@Override
	public boolean isText() {
		return false;
	}
	
	@Override
	public boolean isPureText() {
		return false;
	}

	@Override
	public boolean isCdata() {
		return false;
	}

	@Override
	public boolean isComment() {
		return false;
	}

	@Override
	public boolean isHeader() {
		return false;
	}

	@Override
	public boolean isNameNode() {
		return true;
	}
	
	/**
	 * for REST-1023.
	 * copy from NSAttribute.java in spar-v1.1 project.
	 * @param fullTag
	 * @return
	 */
	public static boolean isNSRelatedTag(String fullTag) {
        if (fullTag == null)
            return false;
        return "xmlns".equals(fullTag)
                || fullTag.startsWith("xmlns:")
                || "targetNamespace".equals(fullTag)
                || "elementFormDefault".equals(fullTag)
                || fullTag.endsWith(":elementFormDefault")
                || "attributeFormDefault".equals(fullTag)
                || fullTag.endsWith(":attributeFormDefault")
                || "schemaLocation".equals(fullTag)
                || fullTag.endsWith(":schemaLocation")
                || "noNamespaceSchemaLocation".equals(fullTag)
                || fullTag.endsWith(":noNamespaceSchemaLocation");
    }
	
	/**
	 * @param xsi: such as xsi:schemaLocation
	 * @return
	 */
	public static boolean isNSRelatedQName(String xsi) {
        if (xsi == null || "".equals(xsi) )
            return false;
        if( xsi.startsWith(XMLConstants.XMLNS_ATTRIBUTE) ) return true;
        
        String[] strs = xsi.split(":");
        if( strs.length==1 ){
        	if( strs[0].startsWith(XMLConstants.XMLNS_ATTRIBUTE) ){
        		return true;
        	}
        }else if( strs.length==2 ){
        	if( XMLConstants.XMLNS_ATTRIBUTE.equals(strs[0]) ) return true;
        	return isNSRelatedTag(strs[1]);
        }
        return false;
    }

    public static boolean isNSRelatedQName(QName qname) {
        if (qname == null)
            return false;
        String prefix = qname.getPrefix();
        if (prefix != null) {
            if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
                return true;
            }
        }
        return isNSRelatedTag(qname.getLocalPart());
    }

}